using System;
using System.Threading;

namespace UI.Utils;

public class IntIdGenerator
{
    private const int StartYear = 2025; // 起始年份，减少时间戳位数
    private readonly int _machineId;
    private int _sequence = 0;
    private int _lastTimestamp = -1;
    private readonly object _lock = new object();
    private static readonly IntIdGenerator _generator =  new IntIdGenerator(machineId: 1);

    public static int IntUUID()
    {
        return _generator.NextId();
    }

    public IntIdGenerator(int machineId = 1)
    {
        // 限制机器ID为0-7（3位）
        _machineId = machineId & 0x7;
    }

    public int NextId()
    {
        lock (_lock)
        {
            var timestamp = GetCurrentTimestamp();

            if (timestamp < _lastTimestamp)
            {
                throw new Exception("Clock moved backwards. Refusing to generate id.");
            }

            if (_lastTimestamp == timestamp)
            {
                _sequence = (_sequence + 1) & 0x1FF; // 9位序列号，每毫秒最多生成512个ID
                if (_sequence == 0)
                {
                    // 序列号溢出，等待下一毫秒
                    timestamp = WaitNextMillis(_lastTimestamp);
                    _sequence = 0;
                }
            }
            else
            {
                _sequence = 0;
            }

            _lastTimestamp = timestamp;

            // 组装ID：时间戳(20位) + 机器ID(3位) + 序列号(9位)
            return (timestamp << 12) | (_machineId << 9) | _sequence;
        }
    }

    private int GetCurrentTimestamp()
    {
        // 从起始年份开始计算秒数，减少位数
        var startDate = new DateTime(StartYear, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        return (int)(DateTime.UtcNow - startDate).TotalSeconds;
    }

    private int WaitNextMillis(int lastTimestamp)
    {
        int timestamp = GetCurrentTimestamp();
        while (timestamp <= lastTimestamp)
        {
            Thread.Sleep(1);
            timestamp = GetCurrentTimestamp();
        }
        return timestamp;
    }
}